﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Workflow.Activities;
using System.Workflow.ComponentModel;
using System.ComponentModel;
using Argos.Data.Model;
using Argos.WorkflowServices;
using Argos.Scheduling;
using System.Diagnostics;
using Argos.Diagnostics;

namespace Argos.Workflows
{
	[Browsable(false)]
	public class TargetMonitoringWorkflowBase : StateMachineWorkflowActivity , ITargetMonitoringWorkflow
	{

		#region public new string CompletedStateName { get; set; }

		[Browsable(false)]
		public new string CompletedStateName
		{
			get { return base.CompletedStateName; }
			set { base.CompletedStateName = value; }
		}

		#endregion
		
		#region public new string Description { get; set; }

		[Browsable(false)]
		public new string Description
		{
			get { return base.Description; }
			set { base.Description = value; }
		}

		#endregion
		
		#region public new ActivityCondition DynamicUpdateCondition { get; set; }

		[Browsable(false)]
		public new ActivityCondition DynamicUpdateCondition
		{
			get { return base.DynamicUpdateCondition; }
			set { base.DynamicUpdateCondition = value; }
		}

		#endregion
		
		#region public new bool Enabled { get; set; }

		[Browsable(false)]
		public new bool Enabled
		{
			get { return base.Enabled; }
			set { base.Enabled = value; }
		}

		#endregion
		
		#region public new string InitialStateName { get; set; }

		[Browsable(false)]
		public new string InitialStateName
		{
			get { return base.InitialStateName; }
			set { base.InitialStateName = value; }
		}

		#endregion
		
		#region public new string Name { get; set; }

		[Browsable(false)]
		public new string Name
		{
			get { return base.Name; }
			set { base.Name = value; }
		}

		#endregion

		#region public Guid TargetId { get; set; }

		public static readonly DependencyProperty TargetIdProperty = DependencyProperty.Register("TargetId", typeof(Guid), typeof(TargetMonitoringWorkflowBase));

		/// <summary>
		/// Sets or returns the ID of the target for which the monitoring workflow
		/// has been created.
		/// </summary>
		[Browsable(false)]
		public Guid TargetId
		{
			get { return (Guid)this.GetValue(TargetIdProperty); }
			set { this.SetValue(TargetIdProperty, value); }
		}

		#endregion



		#region List<Schedule> ITargetMonitoringWorkflow.ActiveSchedules { get; set; }

		private static readonly DependencyProperty ActiveSchedulesProperty = DependencyProperty.Register("ActiveSchedules", typeof(List<Schedule>), typeof(TargetMonitoringWorkflowBase));

		[Browsable(false)]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		List<Schedule> ITargetMonitoringWorkflow.ActiveSchedules
		{
			get { return (List<Schedule>)this.GetValue(ActiveSchedulesProperty); }
			set { this.SetValue(ActiveSchedulesProperty, value); }
		}

		#endregion

		#region List<Schedule> ITargetMonitoringWorkflow.BreakSchedules { get; set; }

		private static readonly DependencyProperty BreakSchedulesProperty = DependencyProperty.Register("BreakSchedules", typeof(List<Schedule>), typeof(TargetMonitoringWorkflowBase));

		[Browsable(false)]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		List<Schedule> ITargetMonitoringWorkflow.BreakSchedules
		{
			get { return (List<Schedule>)this.GetValue(BreakSchedulesProperty); }
			set { this.SetValue(BreakSchedulesProperty, value); }
		}

		#endregion

		#region bool ITargetMonitoringWorkflow.TargetDisabled { get; set; }

		private static readonly DependencyProperty TargetDisabledProperty =
			DependencyProperty.Register("TargetDisabled", typeof(bool), typeof(TargetMonitoringWorkflowBase));

		[Browsable(false)]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		bool ITargetMonitoringWorkflow.TargetDisabled
		{
			get { return (bool)GetValue(TargetDisabledProperty); }
			set { SetValue(TargetDisabledProperty, value); }
		}

		#endregion

		#region TimeSpan ITargetMonitoringWorkflow.TestInterval { get; set; }

		private static readonly DependencyProperty TestIntervalProperty = DependencyProperty.Register("TestInterval", typeof(TimeSpan), typeof(TargetMonitoringWorkflowBase));

		[Browsable(false)]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		TimeSpan ITargetMonitoringWorkflow.TestInterval
		{
			get { return (TimeSpan)this.GetValue(TestIntervalProperty); }
			set { this.SetValue(TestIntervalProperty, value); }
		}

		#endregion



		#region protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)

		/// <summary>
		/// Executes the monitoring workflow.
		/// </summary>
		protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
		{
			if (this.TargetId == Guid.Empty)
				throw new ArgumentException("The 'TargetId' property must not be an empty Guid.");

			return base.Execute(executionContext);
		}

		#endregion

		#region protected bool IsPaused()

		/// <summary>
		/// Returns whether the currently monitored target is currently paused or not.
		/// </summary>
		/// <returns>Returns true if the target is currently paused. Otherwise false.</returns>
		protected bool IsPaused()
		{
			List<Schedule> breaks = ((ITargetMonitoringWorkflow)this).BreakSchedules;

			// If the scheduled breaks list is not null, and that list contains at least one
			// schedule that defines a current occurrence, the target is in a break and will
			// not be monitored.
			if (null != breaks && null != breaks.FirstOrDefault(s => null != s.CurrentOccurrence))
				return true;


			List<Schedule> actives = ((ITargetMonitoringWorkflow)this).ActiveSchedules;

			// If the monitoring schedules list contains at least one schedule that defines a
			// current occurrence, the target is currently being monitored and is not paused.
			if (null != actives && null != actives.FirstOrDefault(s => null != s.CurrentOccurrence))
				return false;


			// If no schedules are found that either define a break or activity, the target
			// is assumed to be paused.
			return true;
		}

		#endregion
	}
}
